home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 35
/
Amiga Format AFCD35 (Issue 119, Jan 1999).iso
/
-screenplay-
/
hd_installers
/
-whdload-
/
whdload_dev
/
src
/
sources
/
savegame.s
< prev
next >
Wrap
Text File
|
1998-07-16
|
15KB
|
746 lines
;*---------------------------------------------------------------------------
; :Program. savegame.s
; :Contents. routine for multiple save game support
; it creates an interface from which the user can choice between
; 9 different savegames, a description can be entered for each
; savegame, all savegames will be stored in one single file which
; grows dynamically
; the savegames must have always the same size
; :Author. Wepl
; :Version. $Id: savegame.s 1.1 1998/06/27 23:53:54 jah Exp jah $
; :History. 14.06.98 extracted from Interphase slave
; 15.06.98 returncode fixed
; problem with savegames larger than $7fff fixed
; :Requires. _keyexit byte variable containing rawkey code
; _exit function to quit
; :Copyright. Public Domain
; :Language. 68000 Assembler
; :Translator. Barfly V2.9
; :To Do.
;---------------------------------------------------------------------------*
; this is a example sequence to use the savegame routine
; during execution some custom registers will be destroyed, if the installed
; program does not refresh them itself, it must be done after calling the
; savegame routine
IFEQ 1
move.l #100,d0 ;savegame size
lea $3e900,a0 ;address of savegame
lea $65000,a1 ;free mem for screen
bsr _sg_load
; move.w #$4100,(_custom+bplcon0)
; move.w #320/8*3,(_custom+bpl1mod)
; move.l #$00000eee,(_custom+color)
ENDC
;--------------------------------
; IN: d0 = ULONG size (only on function save required)
; a0 = APTR address of load/save area
; a1 = APTR space for the screen ($2800 bytes)
; OUT: d0 = BOOL success
; d1/a0/a1 destroyed
MAXNAMELEN = 40
LINE = 320/8
SCREEN = LINE*200
SAVEDIRLEN = 4+10+(10*MAXNAMELEN)
CHARHEIGHT = 5
CHARWIDTH = 5
INCLUDE macros/ntypes.i
NSTRUCTURE SaveGame,0
NLONG sg_screen
NLONG sg_size
NLONG sg_address
NLONG sg_old68
NLONG sg_old6c
NWORD sg_oldintena
NWORD sg_olddmacon
NSTRUCT sg_save_names,10*MAXNAMELEN
NSTRUCT sg_save_flags,10
NSTRUCT sg_save_id,4
NSTRUCT sg_tmpname,MAXNAMELEN
NWORD sg_c_x
NWORD sg_c_y
NBYTE sg_key
NBYTE sg_c_on
NBYTE sg_success
NALIGNLONG
NLABEL sg_SIZEOF
;--------------------------------
; print save game directory
; IN: -
; OUT: -
XBASE = 50
YBASE = 40
YSKIP = 15
_sg_printdir moveq #XBASE,d0 ;x-pos
moveq #YBASE-YSKIP,d1 ;first line
moveq #'1',d2
moveq #0,d3 ;amount saves
.next add.w #YSKIP,d1 ;line skip
bsr _pc
movem.l d0/d2,-(a7)
add.w #15,d0
sub.w #'1',d2
mulu.w #MAXNAMELEN,d2
lea (sg_save_names,a5),a0
add.w d2,a0
bsr _ps
movem.l (a7)+,d0/d2
addq.b #1,d2
cmp.b #'9',d2
bls .next
rts
;--------------------------------
; save a savegame
; IN: D0 = size of the savegame
; A0 = address to load savegame on
; A1 = address of free memory for screen ($2800 bytes)
; OUT: D0 = BOOL success
_sg_save moveq #0,d1
bra _sg_degrade
_sg_save_in bsr _sg_loaddir
.start moveq #7,d1
lea _save,a0
bsr _psc
add.w #8,d1
lea _saveselect,a0
bsr _psc
add.w #8,d1
lea _esc,a0
bsr _psc
bsr _sg_printdir
.keyloop bsr _sg_get_key
cmp.b #$45,d0
beq _sg_restore
lea (_keytrans),a0
move.b (a0,d0.w),d1
cmp.b #'1',d1
blo .keyloop
cmp.b #'9',d1
bhi .keyloop
moveq #XBASE+9,d0
sub.w #'1',d1
move.w d1,d6 ;D6 = save no.
mulu #YSKIP,d1
add.w #YBASE-5,d1
move.w d0,d2
add.w #210,d2
move.w d1,d3
add.w #YSKIP-1,d3
bsr _sg_rect
move.w d6,d0
mulu.w #MAXNAMELEN,d0
lea (sg_save_names,a5),a3
add.w d0,a3 ;A3 = save name
move.l a3,a0
lea (sg_tmpname,a5),a1
.cpy move.b (a0)+,(a1)+
bne .cpy
.chkname moveq #-1,d5
move.l a3,a0
.cnt addq.w #1,d5 ;D5 = charpos in save name
tst.b (a0)+
bne .cnt
move.w d5,d0
mulu #CHARWIDTH,d0
add.w #XBASE+15,d0
move.w d0,(sg_c_x,a5)
move.w d6,d1
mulu #YSKIP,d1
add.w #YBASE,d1
move.w d1,(sg_c_y,a5)
st (sg_c_on,a5)
moveq #15,d1
lea _saveinsert,a0
bsr _psc
.nextkey bsr _sg_get_key
cmp.b #$43,d0 ;enter
beq .return
cmp.b #$44,d0 ;return
beq .return
cmp.b #$41,d0 ;backspace
beq .bs
cmp.b #$46,d0 ;delete
beq .bs
cmp.b #$45,d0 ;escape
beq .esc
cmp.w #MAXNAMELEN-1,d5
beq .nextkey
lea (_keytrans),a0
move.b (a0,d0.w),d2
beq .nextkey
move.b d2,(a3,d5.w)
addq.w #1,d5
move.w (sg_c_x,a5),d0
move.w (sg_c_y,a5),d1
add.w #CHARWIDTH,(sg_c_x,a5)
bsr _pc
bra .nextkey
.bs tst.w d5
beq .nextkey
bsr _sg_cursoroff
subq.w #1,d5
clr.b (a3,d5.w)
bra .chkname
.esc bsr _sg_cursoroff
lea (sg_tmpname,a5),a0
move.l a3,a1
.cpy2 move.b (a0)+,(a1)+
bne .cpy2
bsr _sg_initscr
bra .start
.return tst.w d5 ;a name specified ?
beq .esc
bsr _sg_cursoroff
moveq #15,d1
lea _saveconfirm,a0
bsr _psc
.nextkey2 bsr _sg_get_key
cmp.b #$45,d0 ;escape
beq .esc
cmp.b #$43,d0 ;enter
beq .confirmed
cmp.b #$44,d0 ;return
bne .nextkey2
.confirmed lea (sg_save_flags,a5),a0
st (a0,d6.w)
move.l #SAVEDIRLEN,d0 ;size
moveq #0,d1 ;offset
lea (_sg_name),a0 ;filename
lea (sg_save_id,a5),a1 ;address
move.w #resload_SaveFileOffset,a2
bsr _sg_exec_resload
move.l (sg_size,a5),d0 ;size
move.l #SAVEDIRLEN,d1
bra .loopin
.loop add.l d0,d1 ;offset
.loopin subq.w #1,d6
bpl .loop
lea (_sg_name),a0 ;filename
move.l (sg_address,a5),a1 ;address
move.w #resload_SaveFileOffset,a2
bsr _sg_exec_resload
st (sg_success,a5)
bra _sg_restore
;--------------------------------
; disable text cursor
; IN: -
; OUT: -
_sg_cursoroff sf (sg_c_on,a5)
move.w (sg_c_x,a5),d0
move.w (sg_c_y,a5),d1
move.w #' ',d2
bra _pc
;--------------------------------
; clear screen
; IN: -
; OUT: -
_sg_clrscr movem.l d0/a0,-(a7)
move.l (sg_screen,a5),a0
move.w #(320*256/8)/4-1,d0
.clr clr.l (a0)+
dbf d0,.clr
movem.l (a7)+,d0/a0
rts
;--------------------------------
; init screen
; IN: -
; OUT: -
_sg_initscr movem.l d0-d3/a0,-(a7)
bsr _sg_clrscr
;draw border
; moveq #0,d0
; moveq #0,d1
; move.w #319,d2
; move.w #199,d3
; bsr _sg_rect
;print info
move.w #180,d1
lea _info1,a0
bsr _psc
add.w #8,d1
lea _info2,a0
bsr _psc
movem.l (a7)+,d0-d3/a0
rts
;--------------------------------
; load a savegame
; IN: A0 = address to load savegame on
; A1 = address of free memory for screen ($2800 bytes)
; OUT: D0 = BOOL success
_sg_load moveq #-1,d1
bra _sg_degrade
_sg_load_in bsr _sg_loaddir
beq .nosavegame
.start moveq #7,d1
lea _load,a0
bsr _psc
add.w #8,d1
lea _loadselect,a0
bsr _psc
add.w #8,d1
lea _esc,a0
bsr _psc
bsr _sg_printdir
lea (sg_save_names,a5),a0
moveq #0,d0
.keyloop bsr _sg_get_key
cmp.b #$45,d0
beq _sg_restore
lea (_keytrans),a0
moveq #0,d1
move.b (a0,d0.w),d1
cmp.b #'1',d1
blo .keyloop
cmp.b #'9',d1
bhi .keyloop
lea (sg_save_flags,a5),a0
tst.b (-'1',a0,d1.w)
beq .keyloop
moveq #XBASE+9,d0
sub.w #'1',d1
move.w d1,d6 ;D6 = save no.
mulu #YSKIP,d1
add.w #YBASE-5,d1
move.w d0,d2
add.w #210,d2
move.w d1,d3
add.w #YSKIP-1,d3
bsr _sg_rect
moveq #15,d1
lea _loadconfirm,a0
bsr _psc
.nextkey2 bsr _sg_get_key
cmp.b #$43,d0 ;enter
beq .confirmed
cmp.b #$44,d0 ;return
beq .confirmed
cmp.b #$45,d0 ;escape
bne .nextkey2
bsr _sg_initscr
bra .start
.confirmed move.l (sg_size,a5),d0 ;size
move.l #SAVEDIRLEN,d1
bra .loopin
.loop add.l d0,d1 ;offset
.loopin subq.w #1,d6
bpl .loop
lea (_sg_name),a0 ;filename
move.l (sg_address,a5),a1 ;address
move.w #resload_LoadFileOffset,a2
bsr _sg_exec_resload
st (sg_success,a5)
bra _sg_restore
.nosavegame moveq #60,d1
lea _loadno1,a0
bsr _psc
add.w #8,d1
lea _loadno2,a0
bsr _psc
bsr _sg_get_key
bra _sg_restore
;--------------------------------
; loads save directory
; IN: -
; OUT: D0 = BOOL success
; flags on D0
_sg_loaddir lea (_sg_name),a0
move.w #resload_GetFileSize,a2
bsr _sg_exec_resload
tst.l d0
beq .nocurrentfile
move.l #SAVEDIRLEN,d0 ;size
moveq #0,d1 ;offset
lea (_sg_name),a0 ;filename
lea (sg_save_id,a5),a1 ;address
move.w #resload_LoadFileOffset,a2
bsr _sg_exec_resload
cmp.l #"Wepl",(sg_save_id,a5)
bne .nocurrentfile
moveq #-1,d0 ;successful loaded
rts
.nocurrentfile lea (sg_save_id,a5),a0
move.w #SAVEDIRLEN/4-1,d0
.clr0 clr.l (a0)+
dbf d0,.clr0
move.l #"Wepl",(sg_save_id,a5)
moveq #0,d0 ;nothing current
rts
;--------------------------------
; execute resload function
_sg_exec_resload
move.w #INTF_INTEN,(intena,a6)
add.l (_resload),a2
jsr (a2)
move.w #INTF_SETCLR!INTF_INTEN,(intena,a6)
clr.l ($144,a6)
clr.l ($14c,a6)
rts
;--------------------------------
_sg_get_key clr.b (sg_key,a5)
moveq #0,d0
.waitdown move.b (sg_key,a5),d0
ble .waitdown
bchg #7,d0
.waitup cmp.b (sg_key,a5),d0
bne .waitup
bclr #7,d0
rts
;--------------------------------
_sg_degrade movem.l d2-d7/a2-a6,-(a7)
link a5,#sg_SIZEOF ;A5 = data
move.l d0,(sg_size,a5)
move.l a0,(sg_address,a5)
move.l a1,(sg_screen,a5)
sf (sg_c_on,a5)
sf (sg_success,a5)
bsr _sg_waitvb
move.w (_custom+intenar),(sg_oldintena,a5)
move.w #$7fff,(_custom+intena)
lea (_custom),a6 ;A6 = _custom
move.w (dmaconr,a6),(sg_olddmacon,a5)
move.w #$7fff,(dmacon,a6)
bsr _sg_initscr
lea (_sg_int68),a0
move.l $68,(sg_old68,a5)
move.l a0,$68
lea (_sg_int6c),a0
move.l $6c,(sg_old6c,a5)
move.l a0,$6c
move.w #INTF_SETCLR|INTF_INTEN|INTF_VERTB|INTF_PORTS,(intena,a6)
tst.b (ciaicr+_ciaa) ;clear all intreq
move.w #INTF_VERTB|INTF_PORTS,(intreq,a6)
bsr _sg_waitvb
move.w #$1200,(bplcon0,a6)
clr.w (bpl1mod,a6)
move.l #$00000eee,(color,a6)
move.w #DMAF_SETCLR|DMAF_MASTER|DMAF_RASTER,(dmacon,a6)
tst.l d1
beq _sg_save_in
bra _sg_load_in
;--------------------------------
_sg_restore bsr _sg_clrscr
move.b (sg_success,a5),d0
ext.w d0
move.w d0,a0 ;a0 = success
bsr _sg_waitvb
move.w #$7fff,(intena,a6)
move.w #$7fff,(dmacon,a6)
move.l (sg_old68,a5),$68
move.l (sg_old6c,a5),$6c
move.w #$7fff,(intreq,a6)
move.w (sg_oldintena,a5),d0
bset #15,d0 ;d0 = intena
move.w (sg_olddmacon,a5),d1
bset #15,d1 ;d1 = dmacon
unlk a5
movem.l (a7)+,d2-d7/a2-a6
move.w d0,(_custom+intena)
bsr _sg_waitvb
move.w d1,(_custom+dmacon)
move.l a0,d0 ;success
rts
;--------------------------------
_sg_int68 movem.l d0-d1,-(a7)
btst #CIAICRB_SP,(ciaicr+_ciaa) ;check int reason
beq .int2_exit
move.b (ciasdr+_ciaa),d0 ;read code
clr.b (ciasdr+_ciaa) ;output LOW (handshake)
or.b #CIACRAF_SPMODE,(ciacra+_ciaa) ;to output
not.b d0
ror.b #1,d0
cmp.b (_keyexit),d0
beq _exit
move.b d0,(sg_key,a5)
moveq #3-1,d1 ;wait because handshake min 75 µs
.int2_w1 move.b (vhposr,a6),d0
.int2_w2 cmp.b (vhposr,a6),d0 ;one line is 63.5 µs
beq .int2_w2
dbf d1,.int2_w1 ;(min=127µs max=190.5µs)
and.b #~(CIACRAF_SPMODE),(ciacra+_ciaa) ;to input
.int2_exit move.w #INTF_PORTS,(intreq,a6)
movem.l (a7)+,d0-d1
rte
;--------------------------------
_sg_int6c move.l (sg_screen,a5),(bplpt,a6)
tst.b (sg_c_on,a5)
beq .1
movem.l d0-d2,-(a7)
move.w (sg_c_x,a5),d0
move.w (sg_c_y,a5),d1
move.w #' ',d2
bchg #0,(sg_c_on,a5)
beq .2
move.w #'_',d2
.2 bsr _pc
movem.l (a7)+,d0-d2
.1 move.w #INTF_VERTB,(intreq,a6)
rte
;--------------------------------
_sg_waitvb waitvb
rts
;--------------------------------
; draw rectangle
; IN: d0 = word x start
; d1 = word y start
; d2 = word x stop
; d3 = word y stop
; OUT: -
_sg_rect bsr _sg_xline
exg d1,d3
bsr _sg_xline
exg d1,d2
exg d1,d3
bsr _sg_yline
exg d0,d3
bra _sg_yline
;--------------------------------
; line in x axis
; IN: d0 = word x start
; d1 = word y start
; d2 = word x stop
; OUT: -
_sg_xline movem.l d0/d2,-(a7)
cmp.w d0,d2
beq .end
bhi .in
exg d0,d2
bra .in
.next addq.w #1,d0
.in bsr _sg_pset
cmp.w d0,d2
bne .next
.end movem.l (a7)+,d0/d2
rts
;--------------------------------
; line in y axis
; IN: d0 = word x start
; d1 = word y start
; d2 = word y stop
; OUT: -
_sg_yline movem.l d1/d2,-(a7)
cmp.w d1,d2
beq .end
bhi .in
exg d1,d2
bra .in
.next addq.w #1,d1
.in bsr _sg_pset
cmp.w d1,d2
bne .next
.end movem.l (a7)+,d1/d2
rts
;--------------------------------
; set a pixel
; IN: d0 = word x start
; d1 = word y start
; OUT: -
_sg_pset move.l d1,-(a7)
bsr _getscrptr
move.w d0,d1
lsr.w #3,d1
add.w d1,a0
moveq #7,d1
and.w d0,d1
neg.w d1
addq.w #7,d1
bset d1,(a0)
move.l (a7)+,d1
rts
;--------------------------------
; IN: d1 = word y start
; OUT: a0 = ptr
_getscrptr move.l (sg_screen,a5),a0
mulu #LINE,d1
add.l d1,a0
rts
;--------------------------------
; print string centered
; IN: d1 = word y
; a0 = cptr string
; OUT: d0 = word new x
_psc move.l a0,-(a7)
moveq #0,d0
.count tst.b (a0)+
beq .1
subq.w #CHARWIDTH,d0
bra .count
.1 asr.w #1,d0
add.w #LINE*4,d0
move.l (a7)+,a0
bra _ps
;--------------------------------
; print string
; IN: d0 = word x
; d1 = word y
; a0 = cptr string
; OUT: d0 = word new x
_ps movem.l d2,-(a7)
moveq #0,d2
bra .in
.next bsr _pc
add.w #CHARWIDTH,d0
.in move.b (a0)+,d2
bne .next
movem.l (a7)+,d2
rts
;--------------------------------
; print char
; IN: d0 = word x
; d1 = word y
; d2 = char
_pc movem.l d0-d5/a0-a1,-(a7)
bsr _getscrptr
sub.w #32,d2
mulu #CHARWIDTH,d2
lea (_font),a1
moveq #CHARHEIGHT-1,d3
.cp
IFD _68020_
bfextu (a1){d2:CHARWIDTH},d1
bfins d1,(a0){d0:CHARWIDTH}
ELSE
move.l d2,d1
lsr.l #4,d1 ;words
add.l d1,d1 ;bytes down rounded to word
move.l (a1,d1.l),d1
move.l d2,d4
and.w #%1111,d4
lsl.l d4,d1
and.l #$ffffffff<<(32-CHARWIDTH),d1
move.l #$ffffffff>>CHARWIDTH,d5
move.l d0,d4
and.w #%1111,d4
lsr.l d4,d1
ror.l d4,d5
move.l d0,d4
lsr.l #4,d4 ;words
add.l d4,d4 ;bytes down rounded to word
and.l d5,(a0,d4.l)
or.l d1,(a0,d4.l)
ENDC
add.l #(_font_-_font)*8/CHARHEIGHT,d2
add.l #LINE*8,d0
dbf d3,.cp
movem.l (a7)+,d0-d5/a0-a1
rts
_font INCBIN pics/pic_font_5x6_br.bin
_font_
;--------------------------------
_sg_name dc.b "savegame",0
_info1 dc.b "special multiple savegame support",0
_info2 dc.b "written by wepl in spring 1998",0
_esc dc.b "press esc to cancel",0
_save dc.b ">>> save a game <<<",0
_saveselect dc.b "select a save position using the keyboard '1' - '9'",0
_saveinsert dc.b " type in a description for this save position ",0
_saveconfirm dc.b " confirm this save operation (return) ",0
_load dc.b ">>> load a game <<<",0
_loadselect dc.b "select a load position using the keyboard '1' - '9'",0
_loadconfirm dc.b " confirm this load operation (return) ",0
_loadno1 dc.b "sorry there is currently no valid savegame to load",0
_loadno2 dc.b "press any key to continue",0
_keytrans dc.b 0,"1234567890",0,0,"0",0,0
dc.b "qwertyuiop",0,0,0,"123"
dc.b "asdfghjkl",0,0,0,0,"456"
dc.b 0,"zxcvbnm,.-",0,0,"789"
dc.b " ",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dc.b "123456789",0,0,0,0,0,0,0
ds.b 16
ds.b 16